#include "modbus.h"
#define MB_SALVE_ADDR	0x01

struct mb_para g_mb_para;
uint8_t iap_flag = 0;  //iap升级

uint16_t* p_reg;  //modbus寄存器地址
uint8_t uart0_frame_end_flag = 0;  //帧结束
uint8_t uart0_rx_buf[UART0_BUF_LENTH];
uint16_t uart0_rx_cnt = 0;

static void _mb_clear_buffer(void);

/* CRC16 */
uint16_t mb_crc16(uint8_t *buf, uint16_t len)
{
    uint16_t crc = 0xffff;
    uint16_t i = 0, j = 0;
    
    for (i = 0; i < len; i++)
    {
        crc ^= buf[i];
        
        for (j = 0; j < 8; j++)
        {
            if (crc & 0x01)
            {
                crc >>= 1;
                crc ^= 0xA001;
            }
            else
            {
                crc >>= 1;
            }				
        }
    }    
    return (crc);
}

/* iap应答 */
void iap_ack(u8 step, u8 ret)
{
	u16 crc16 = 0;
	u8 iap_buf[15];
    u8 i = 0;
	
	iap_buf[i++] = g_mb_para.mb_rx_buf[0];
	iap_buf[i++] = g_mb_para.mb_rx_buf[1];
	iap_buf[i++] = g_mb_para.mb_rx_buf[2];
	iap_buf[i++] = 0x03;
	iap_buf[i++] = 0x00;
	iap_buf[i++] = 0xa1;
	iap_buf[i++] = ret;
	iap_buf[i++] = 0;
	
	crc16 = mb_crc16(&iap_buf[1], i-1);
	iap_buf[i++] = (uint8_t)crc16;
	iap_buf[i++] = (uint8_t)(crc16 >> 8);
	
	iap_buf[i++] = 0x0d;
	iap_buf[i++] = 0x0a;
	
	if (g_mb_para.mb_interface == USART0)
	{
		g_mb_para.mb_tx = uart0_tx;
	}
	
	g_mb_para.mb_tx(iap_buf, i);
}

static uint8_t mb_crc16_check(void)
{
	uint16_t recv_crc16 = 0;
	uint16_t calc_crc16 = 0;
	
	if (g_mb_para.mb_rx_cnt < 3)
	{
		return 0;
	}

	if (g_mb_para.mb_rx_buf[0] == MODBUS_IAP_ADR)
	{
		return 0;
	}

	recv_crc16 = g_mb_para.mb_rx_buf[g_mb_para.mb_rx_cnt - 2] | g_mb_para.mb_rx_buf[g_mb_para.mb_rx_cnt - 1] << 8;
	calc_crc16 = mb_crc16(g_mb_para.mb_rx_buf, g_mb_para.mb_rx_cnt - 2);
	
	return (calc_crc16 == recv_crc16);
}

/* 是否需要iap升级, 0->需要升级 */
u8 iap_check(void)
{
    u8 i = 0;

	if (g_mb_para.mb_rx_buf[0] != MODBUS_IAP_ADR)
	{
		return 1;
	}
	
    if ((g_mb_para.mb_rx_buf[1] == 0x01) 
     && (g_mb_para.mb_rx_buf[2] == 0xa0)
     && (g_mb_para.mb_rx_buf[6] == UART_PRODUCT_CLASS1)
     && (g_mb_para.mb_rx_buf[7] == UART_PRODUCT_CLASS2))
    {
		for(i=0;i<16;i++)
		{
			if(g_mb_para.mb_rx_buf[i+9]!=gUart_Project_Name[i])
			{
				break;
			}
		}

		if(i==16)
		{			
			//*******************返回报文**************
			if(g_mb_para.mb_rx_buf[8] == 0)
			{
				iap_ack(0, 0xFE);
			}
			else if(g_mb_para.mb_rx_buf[8] == 1)
			{
				iap_ack(1, 0);
			}
			else
			{
				iap_ack(2, 0xFF);
			}
			
	        return 0;
		}
    }
    return 1;
}

//0x03: 读寄存器
/* 1byte 从机地址
 * 1byte 功能码:0x03
 * 2bytes 寄存器起始地址
 * 2bytes 寄存器个数
 * 2bytes CRC16
 */
//应答: 从机地址 + 0x03 + 字节数(1B) + N*数据 + CRC16
void mb_master_read_reg(mb_para_t mb_para, uint16_t reg_addr, uint16_t count)
{
	u16 crc16 = 0;
	uint8_t tx_buf[10];

	tx_buf[0] = MB_SALVE_ADDR;
	tx_buf[1] = 0x03;
	tx_buf[2] = reg_addr >> 8;
	tx_buf[3] = reg_addr;
	tx_buf[4] = count >> 8;
	tx_buf[5] = count;
	crc16 = mb_crc16(&tx_buf[0], 6);
	tx_buf[6] = crc16;
	tx_buf[7] = crc16 >> 8;

	if (mb_para->mb_interface == USART0)
	{
		mb_para->mb_tx = uart0_tx;
	}
	
	mb_para->mb_tx(tx_buf, 8);
}


/********
 * 查询BMS数据
 * 
*/
void mb_get_bms_info(void)
{
    if (gLcdSleepFlag)
    {
        return;
    }
    
    g_mb_para.mb_interface = USART0;    // 485
	mb_master_read_reg(&g_mb_para, 0x0000, 4);
}

/***
 * 解析BMS数据
*/
void mb_parse_bms_info(void)
{
	uint8_t op_code = 0;

	op_code = g_mb_para.mb_rx_buf[1];

	if ((op_code != 0x03) && (op_code != 0x06))
	{
		return;
	}

	g_lcd_display_info.pack_v 			= (uint16_t)g_mb_para.mb_rx_buf[3] << 8 | g_mb_para.mb_rx_buf[4];
    g_lcd_display_info.pack_c 			= ((int32_t)g_mb_para.mb_rx_buf[5] << 24 | g_mb_para.mb_rx_buf[6] << 16 | g_mb_para.mb_rx_buf[7] << 8 | g_mb_para.mb_rx_buf[8]);

	g_lcd_display_info.soc 				= (uint16_t)g_mb_para.mb_rx_buf[9] << 8 | g_mb_para.mb_rx_buf[10];
    g_lcd_display_info.bms_status       = ((uint32_t)g_mb_para.mb_rx_buf[133] << 24 | g_mb_para.mb_rx_buf[134] << 16 | g_mb_para.mb_rx_buf[135] << 8 | g_mb_para.mb_rx_buf[136]);

    //SOC状态
    if (BIT_GET(g_lcd_display_info.bms_status, 2))  // 静置
	{
        g_lcd_display_info.soc_status = STANDBY;
	}
	else if (BIT_GET(g_lcd_display_info.bms_status, 0)) // 充电
	{
        g_lcd_display_info.soc_status = CHARGING;
	}
	else if (BIT_GET(g_lcd_display_info.bms_status, 1)) // 放电
	{
        g_lcd_display_info.soc_status = DISCHARGING;
	}

	g_lcd_manager.lcd_event = REFRESH_DATA;
}

/* 清缓冲 */
static void _mb_clear_buffer(void)
{
	uart0_frame_end_flag = FREE;
	my_memset((char*)&uart0_rx_buf[0], 0, UART0_BUF_LENTH);
	uart0_rx_cnt = 0;
}

void modbus_master_task(void)
{
	if (uart0_frame_end_flag == FRAME_END)
	{
		uart0_frame_end_flag = FREE;
		g_mb_para.mb_interface = USART0;
		g_mb_para.mb_rx_buf = uart0_rx_buf;
		g_mb_para.mb_rx_cnt = uart0_rx_cnt;

		if (mb_crc16_check())
		{
			g_lcd_display_info.comm_state = UART0;
			g_lcd_manager.comm_disconnect_cnt = 0;
			mb_parse_bms_info();  /* 解析bms_info */
		}
		else if (!iap_check())
		{
			iap_flag = 1;  //升级
		}
		_mb_clear_buffer();
	}
}
